package com.easy.cloud.web.service.upms.biz.controller;

import cn.hutool.core.util.StrUtil;
import com.easy.cloud.web.component.core.response.HttpResult;
import com.easy.cloud.web.component.log.annotation.SysLog;
import com.easy.cloud.web.component.log.annotation.SysLog.Action;
import com.easy.cloud.web.component.security.annotation.Inner;
import com.easy.cloud.web.component.security.domain.AuthenticationUser;
import com.easy.cloud.web.component.security.util.SecurityUtils;
import com.easy.cloud.web.service.upms.api.dto.*;
import com.easy.cloud.web.service.upms.api.vo.UserVO;
import com.easy.cloud.web.service.upms.biz.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import java.util.List;

/**
 * User API
 *
 * @author Fast Java
 * @date 2023-08-03 14:25:41
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping(value = "user")
@Api(value = "用户管理", tags = "用户管理")
public class UserController {

    private final IUserService userService;

    /**
     * 新增
     *
     * @param userDTO 新增数据
     * @return 新增数据
     */
    @PostMapping(value = "save")
    @PreAuthorize("@pms.hasPermission('system:user:add')")
    @SysLog(value = "新增用户", action = Action.ADD)
    @ApiOperation(value = "新增用户")
    public HttpResult<UserVO> save(@Validated @RequestBody UserDTO userDTO) {
        return HttpResult.ok(userService.save(userDTO));
    }

    /**
     * 更新
     *
     * @param userDTO 新增数据
     * @return 更新数据
     */
    @PostMapping(value = "update")
    @PreAuthorize("@pms.hasPermission('system:user:update')")
    @SysLog(value = "更新用户", action = Action.UPDATE)
    @ApiOperation(value = "更新用户")
    public HttpResult<UserVO> update(@Validated @RequestBody UserDTO userDTO) {
        return HttpResult.ok(userService.update(userDTO));
    }

    /**
     * 根据ID移除数据
     *
     * @param userId ID
     * @return 是否删除成功
     */
    @GetMapping(value = "remove/{userId}")
    @PreAuthorize("@pms.hasPermission('system:user:delete')")
    @SysLog(value = "删除用户", action = Action.DELETE)
    @ApiOperation(value = "删除用户")
    public HttpResult<Boolean> removeById(@PathVariable @NotBlank(message = "当前ID不能为空") String userId) {
        return HttpResult.ok(userService.removeById(userId));
    }

    /**
     * 根据ID获取详情
     *
     * @param userId ID
     * @return 详情数据
     */
    @GetMapping(value = "detail/{userId}")
    @PreAuthorize("@pms.hasPermission('system:user:query')")
    @SysLog(value = "获取用户详情（仅限于常规信息，不包含角色、部门等信息）", action = Action.FIND)
    @ApiOperation(value = "获取用户详情（仅限于常规信息，不包含角色、部门等信息）")
    public HttpResult<UserVO> detailById(@PathVariable @NotBlank(message = "当前ID不能为空") String userId) {
        if (StrUtil.isBlank(userId)) {
            userId = SecurityUtils.getAuthenticationUser().getId();
        }

        return HttpResult.ok(userService.detailById(userId));
    }


    /**
     * 获取当前用户基本信息，包括用户角色，部门，权限等
     *
     * @return 详情数据
     */
    @GetMapping(value = "base/detail")
    @PreAuthorize("@pms.hasPermission('system:user:query')")
    @SysLog(value = "获取用户基本详情", action = Action.FIND)
    @ApiOperation(value = "获取用户基本详情")
    public HttpResult<UserVO> baseDetail(@RequestParam(required = false) String userId) {
        if (StrUtil.isBlank(userId)) {
            userId = SecurityUtils.getAuthenticationUser().getId();
        }

        return HttpResult.ok(userService.baseDetail(userId));
    }

    /**
     * TODO 所有数据列表，查询参数自定义
     *
     * @return 查询列表
     */
    @GetMapping(value = "list")
    @PreAuthorize("@pms.hasPermission('system:user:query')")
    @SysLog(value = "用户列表", action = Action.FIND)
    @ApiOperation(value = "用户列表")
    public HttpResult<List<UserVO>> list(UserQueryDTO userQueryDTO) {
        return HttpResult.ok(userService.list(userQueryDTO));
    }

    /**
     * 根据条件查询分页数据
     *
     * @return 查询分页数据
     */
    @GetMapping(value = "page")
    @PreAuthorize("@pms.hasPermission('system:user:query')")
    @SysLog(value = "用户分页", action = Action.FIND)
    @ApiOperation(value = "用户分页")
    public HttpResult<Page<UserVO>> page(UserQueryDTO userQueryDTO) {
        return HttpResult.ok(userService.page(userQueryDTO));
    }


    /**
     * 根据登录名获取用户详情
     *
     * @param userName 登录名
     * @return com.easy.cloud.web.component.core.response.HttpResult<com.easy.cloud.web.service.upms.biz.v1.domain.vo.UserVO>
     */
    @Inner
    @GetMapping("account/login/detail")
    @SysLog(value = "根据用户名获取用户详情", action = Action.FIND)
    @ApiOperation(value = "根据用户名获取用户详情")
    public HttpResult<UserVO> loadLoginUserByUsername(@RequestParam(value = "userName") @NotBlank(message = "用户名不能为空") String userName) {
        return HttpResult.ok(userService.loadLoginUserByUsername(userName));
    }

    /**
     * 根据传入对象获取用户详情
     *
     * @param userLoginDTO 第三方登录信息
     * @return com.easy.cloud.web.component.core.response.HttpResult<com.easy.cloud.web.service.upms.biz.v1.domain.vo.UserVO>
     */
    @Inner
    @PostMapping("social/login/detail")
    @SysLog(value = "根据第三方登录信息获取登录想起", action = Action.FIND)
    @ApiOperation(value = "根据第三方登录信息获取登录想起")
    public HttpResult<UserVO> loadLoginUserBySocial(@RequestBody @Validated UserLoginDTO userLoginDTO) {
        return HttpResult.ok(userService.loadLoginUserBySocial(userLoginDTO.getType(), userLoginDTO));
    }

    /**
     * 绑定角色
     *
     * @param userBindDTO 用户信息
     * @return success/false
     */
    @PostMapping("/bind/role")
    @PreAuthorize("@pms.hasPermission('system:user:update')")
    @SysLog(value = "绑定用户角色", action = Action.UPDATE)
    @ApiOperation(value = "绑定用户角色")
    public HttpResult<UserVO> bindUserRole(@RequestBody UserBindDTO userBindDTO) {
        AuthenticationUser authenticationUser = SecurityUtils.getAuthenticationUser();
        userBindDTO.setId(authenticationUser.getId());
        return HttpResult.ok(userService.bindUserRole(userBindDTO));
    }


    /**
     * 注册用户
     *
     * @param userRegisterDTO 用户信息
     * @return success/false
     */
    @Inner
    @PostMapping("/register")
    @SysLog(value = "注册用户", action = Action.ADD)
    @ApiOperation(value = "注册用户")
    public HttpResult<UserVO> registerUser(@RequestBody @Validated UserRegisterDTO userRegisterDTO) {
        return HttpResult.ok(userService.registerUser(userRegisterDTO));
    }


    /**
     * 锁定指定用户
     *
     * @param userId 用户ID
     * @return HttpResult
     */
    @GetMapping("/lock/{userId}")
    @PreAuthorize("@pms.hasPermission('system:user:lock')")
    @SysLog(value = "锁定指定用户", action = Action.UPDATE)
    @ApiOperation(value = "锁定指定用户")
    public HttpResult<UserVO> lockUser(@PathVariable String userId) {
        return HttpResult.ok(userService.lockUser(userId));
    }

    /**
     * 修改密码
     *
     * @param userBindDTO 修改密码参数
     * @return HttpResult
     */
    @PostMapping("/password")
    @SysLog(value = "修改用户密码", action = Action.UPDATE)
    @ApiOperation(value = "修改用户密码")
    public HttpResult<Boolean> changePassword(@RequestBody UserBindDTO userBindDTO) {
        AuthenticationUser authenticationUser = SecurityUtils.getAuthenticationUser();
        userBindDTO.setId(authenticationUser.getId());
        userService.changePassword(userBindDTO);
        return HttpResult.ok(true);
    }

    /**
     * 密码校验
     *
     * @param userBindDTO 密码校验数据
     * @return HttpResult
     */
    @PostMapping("/check")
    @SysLog(value = "校验用户密码", action = Action.FIND)
    @ApiOperation(value = "校验用户密码")
    public HttpResult<String> checkPassword(@RequestBody UserBindDTO userBindDTO) {
        AuthenticationUser authenticationUser = SecurityUtils.getAuthenticationUser();
        userBindDTO.setId(authenticationUser.getId());
        Boolean checkPassword = userService.checkPassword(userBindDTO);
        if (checkPassword) {
            return HttpResult.ok("ok");
        }
        return HttpResult.fail("密码错误");
    }

    /**
     * 实名认证
     *
     * @param userBindDTO 实名认证信息
     * @return void
     */
    @PostMapping("bind/tel")
    @SysLog(value = "绑定用户电话", action = Action.UPDATE)
    @ApiOperation(value = "绑定用户电话")
    public HttpResult<Boolean> bindUserTel(@RequestBody UserBindDTO userBindDTO) {
        userService.bindUserTel(userBindDTO);
        return HttpResult.ok(true);
    }
}